package com.koron.standard.jobStock.experiment.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koron.standard.bean.query.PageQuery;
import com.koron.standard.jobStock.experiment.bean.dto.ExperimentDTO;
import com.koron.standard.jobStock.experiment.bean.dto.ExperimentItemDTO;
import com.koron.standard.jobStock.experiment.bean.enums.paramType;
import com.koron.standard.jobStock.experiment.bean.po.Experiment;
import com.koron.standard.jobStock.experiment.bean.po.ExperimentParams;
import com.koron.standard.jobStock.experiment.bean.query.ExperimentQuery;
import com.koron.standard.jobStock.experiment.bean.vo.ExperimentVO;
import com.koron.standard.jobStock.experiment.mapper.ExperimentMapper;
import com.koron.standard.utils.CommonUtils;
import com.koron.standard.utils.StandardCodeTools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 试验标准信息(Experiment)表服务实现类
 *
 * @author jzp
 * @since 2021-09-16
 */
@Service
public class ExperimentService extends ServiceImpl<ExperimentMapper, Experiment> {

    @Autowired
    private ExperimentItemService experimentItemService;

    @Autowired
    private ExperimentParamsService experimentParamsService;

    public Page<ExperimentVO> page(PageQuery<ExperimentVO> pageQuery, ExperimentQuery query) {
        // 设置默认只查有权限的水司数据
        query.setAppids(CommonUtils.getDefaultAppids(query.getAppids()));
        query.setPublicStatus(CommonUtils.getDefaultPublicStatus(query.getPublicStatus()));

        QueryWrapper<ExperimentVO> wrapper = new QueryWrapper<>();
        wrapper.like(StrUtil.isNotEmpty(query.getCode()), "c_experiment.code", query.getCode());
        wrapper.like(StrUtil.isNotEmpty(query.getName()), "c_experiment.name", query.getName());
        wrapper.eq(StrUtil.isNotEmpty(query.getTypeId()), "c_experiment.type_id", query.getTypeId());
        wrapper.like(StrUtil.isNotEmpty(query.getTypeName()), "c_type.name", query.getTypeName());

        if (query.getPublicStatus() != null && query.getPublicStatus() > 0) {
            // 如果是共有的
            wrapper.and(w -> w.eq("c_experiment.public_status", query.getPublicStatus())
                    .or(CollUtil.isNotEmpty(query.getAppids()))
                    .in(CollUtil.isNotEmpty(query.getAppids()), "c_experiment.appid", query.getAppids()));
        } else {
            wrapper.in(CollUtil.isNotEmpty(query.getAppids()), "c_experiment.appid", query.getAppids());
        }

        wrapper.eq(query.getStatus()!=null, "c_experiment.status", query.getStatus());
        wrapper.eq(StrUtil.isNotEmpty(query.getDeptId()), "c_experiment.dept_id", query.getDeptId());
        wrapper.like(StrUtil.isNotEmpty(query.getDeptName()), "c_experiment.dept_name", query.getDeptName());
        if (CollUtil.isNotEmpty(query.getDates())) {
            wrapper.between("c_experiment.create_time", query.getDates().get(0), query.getDates().get(1));
        }
        wrapper.eq("c_experiment.delete_flag", 0);

        Page<ExperimentVO> page = pageQuery.convertPage();
        List<OrderItem> orders = pageQuery.getOrders();
        for (OrderItem order : orders) {
            if (order.getColumn().equals("type_name")) {
                order.setColumn("c_type.name");
            } else if (order.getColumn().equals("app_name")) {
                order.setColumn("s_app.name");
            } else {
                order.setColumn("c_experiment." + order.getColumn());
            }
        }
        getBaseMapper().selectPageVo(page, wrapper);
        return page;
    }

    public ExperimentDTO getDtoById(String id) {
        // 参数主表数据
        ExperimentVO experimentVO = getBaseMapper().getVoById(id);
        ExperimentDTO experimentDTO = new ExperimentDTO();
        BeanUtils.copyProperties(experimentVO, experimentDTO);

        // 查询作业项目数据
        List<ExperimentItemDTO> experimentItemDTOs = experimentItemService.getTreeByExperimentId(id);
        experimentDTO.setItemDTOs(experimentItemDTOs);

        // 查询参数
        List<ExperimentParams> experimentParams = experimentParamsService.listByExperimentId(id);
        // 参数分解
        experimentDTO.setEnvParams(experimentParams.stream().filter(e -> paramType.ENV.getType().equals(e.getType())).collect(Collectors.toList()));
        experimentDTO.setDeviceParams(experimentParams.stream().filter(e -> paramType.DEVICE.getType().equals(e.getType())).collect(Collectors.toList()));

        return experimentDTO;
    }

    public void saveDto(ExperimentDTO experimentDTO) {
        // 设置编码
        experimentDTO.setCode(StandardCodeTools.getExperimentJobCode());

        // 默认草稿
        experimentDTO.setStatus(0);

        // 保存
        updateDtoById(experimentDTO);

    }

    /**
     * 筛选除有标准的分类id
     */
    public List<String> filterTypeIds(List<String> typeIds) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CollUtil.isNotEmpty(typeIds), Experiment::getTypeId, typeIds);
        List<Experiment> list = list(wrapper);
        return list.stream().map(Experiment::getTypeId).distinct().collect(Collectors.toList());
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void updateDtoById(ExperimentDTO experimentDTO) {
        // 1. 删除所有子项-日常维护标准下作业项目树
        experimentItemService.removeByExperimentId(experimentDTO.getId());
        experimentParamsService.removeByExperimentId(experimentDTO.getId());

        // 2. 保存或更新基本信息
        saveOrUpdate(experimentDTO);

        // 3. 保存节点信息
        List<ExperimentItemDTO> experimentItemDTOs = Optional.ofNullable(experimentDTO.getItemDTOs()).orElse(new ArrayList<>());
        for (ExperimentItemDTO experimentItemDTO : experimentItemDTOs) {
            experimentItemDTO.setExperimentId(experimentDTO.getId());
            experimentItemService.saveRootDto(experimentItemDTO); // 会递归保存所有子节点信息
        }

        // 4. 保存环境信息
        // 参数合并
        List<ExperimentParams> experimentParams = experimentDTO.getEnvParams();
        experimentParams.addAll(experimentDTO.getDeviceParams());
        if (CollUtil.isNotEmpty(experimentParams)) {
            experimentParams.forEach(e -> e.setExperimentId(experimentDTO.getId()));
            experimentParamsService.saveBatch(experimentParams);
        }

    }

    public void updateToPublic(List<String> ids) {
        List<Experiment> experiments = new ArrayList<>();
        for (String id : ids) {
            Experiment experiment = new Experiment();
            experiment.setId(id);
            experiment.setPublicStatus(1);
            experiments.add(experiment);
        }
        updateBatchById(experiments);
    }

    public void updateStatus(String id, Integer status) {
        LambdaUpdateWrapper<Experiment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Experiment::getId, id);
        wrapper.set(Experiment::getStatus, status);
        update(wrapper);
    }
}
